/*
 * @version: 1.0
 * @Author: zhl
 * @Date: 2022-02-10 13:47:46
 * @LastEditors: zhl
 * @LastEditTime: 2022-04-29 10:53:43
 * @Description: 文件实现业务描述
 */
#include "JsonManager.h"
#include "CDBManager.h"
#include "CLogger.h"
#include "app.h"
#include "common.h"
#include "json.hpp"
#include "CReportManager.h"
#include "JsonTranslator.hpp"
#include <sys/types.h>
#include <signal.h>
#include <thread>

JsonManager JsonManager::c_json_manager;

JsonManager::JsonManager(/* args */){

}

JsonManager::~JsonManager(){

}
//
JsonManager &JsonManager::getInstance(){
    return c_json_manager;
}

void JsonManager::remove_config_all(){
    remove_config_gateway();
    remove_config_task();
    remove_config_terminal();
    remove_config_linkage();
    remove_config_scene();
}
void JsonManager::remove_config_gateway(){
    CDBManager::getInstance()->remove_dlt645_data_type();
    CDBManager::getInstance()->remove_dlt698_data_type();
    CDBManager::getInstance()->remove_protocol_rule();
    CDBManager::getInstance()->remove_edge_device();
    CDBManager::getInstance()->remove_serial_info();
    CDBManager::getInstance()->remove_iec104_rules();
    CDBManager::getInstance()->remove_104info_obj();
    CDBManager::getInstance()->remove_dlt698_run_params();
    CDBManager::getInstance()->remove_dlt698_mapping_points();
}
void JsonManager::remove_config_task(){
    CDBManager::getInstance()->remove_task();
    CDBManager::getInstance()->remove_task_item();
}
void JsonManager::remove_config_terminal(){
    CDBManager::getInstance()->remove_terminal();
    CDBManager::getInstance()->remove_modbus_point();
    CDBManager::getInstance()->remove_dlt645_point();
    CDBManager::getInstance()->remove_dlt698_point();
    CDBManager::getInstance()->remove_modbus_request();
    CDBManager::getInstance()->remove_dlt645_request();
    CDBManager::getInstance()->remove_dlt698_request();
    CDBManager::getInstance()->remove_modbus_command();
    CDBManager::getInstance()->remove_dlt645_commands();
    CDBManager::getInstance()->remove_dlt645_freeze_request();
    CDBManager::getInstance()->remove_dlt645_freeze_time();
    CDBManager::getInstance()->remove_terminal_products();
}
void JsonManager::remove_config_linkage(){
    CDBManager::getInstance()->remove_linkage_rule();
    CDBManager::getInstance()->remove_linkage_multi_rules();
    CDBManager::getInstance()->remove_linkage_conditions();
    CDBManager::getInstance()->remove_linkage_actions();
}
//
void JsonManager::remove_config_scene(){
    CDBManager::getInstance()->remove_scene_actions();
    CDBManager::getInstance()->remove_scenes();
}
//
void send_cmd_resp(int64_t dev_id, int64_t req_id, std::string command, int code, std::string err_msg){
    CReportManager::getInstance().cmd_response(0ll, req_id, command, 0, "配置命令执行成功");
}
int JsonManager::parse(std::shared_ptr<CConfigManager> cm, std::shared_ptr<TaskManager> tm, std::shared_ptr<CMosquittoManager> mm, std::shared_ptr<DataCenterManager> dcm, std::string data){
    json j = json::parse(data);
    
    if(j.contains("command") && j.contains("commandType") && (0 == j["commandType"].get<std::string>().compare("REQ"))){
        
        std::string command = j["command"].get<std::string>();
        int64_t cmd_id = j["commandId"].get<int64_t>();
        if(0 == command.compare("CMD_SET_CONFIG_ALL")){
            CReportManager::getInstance().cmd_response(0ll, cmd_id, command, 0, "配置命令执行成功");
            remove_config_all();
            parse_config(cm, tm, mm,dcm, data);
        } else if(0 == command.compare("CMD_SET_CONFIG_TASK")){
            CReportManager::getInstance().cmd_response(0ll, cmd_id, command, 0, "配置任务命令执行成功");
            remove_config_task();
            parse_config(cm, tm, mm, dcm, data);
        } else if(0 == command.compare("CMD_SET_CONFIG_GATEWAY")){
            CReportManager::getInstance().cmd_response(0ll, cmd_id, command, 0, "配置网关命令执行成功");
            remove_config_gateway();
            parse_config(cm, tm, mm, dcm, data);
        } else if(0 == command.compare("CMD_SET_CONFIG_TERMINAL")){
            CReportManager::getInstance().cmd_response(0ll, cmd_id, command, 0, "配置终端命令执行成功");
            remove_config_terminal();    
            parse_config(cm, tm, mm, dcm, data);
        } else if(0 == command.compare("CMD_SET_CONFIG_LINKAGE")){
            CReportManager::getInstance().cmd_response(0ll, cmd_id, command, 0, "配置联动命令执行成功");
            remove_config_linkage();
            parse_config(cm, tm, mm, dcm, data);
        } else if(0 == command.compare("CMD_SET_COMMAND_RULE")){
            run_cmd(cm, tm, mm, TASK_TYPE_SET_CMD_RULE, cmd_id, data);
        } else if(0 == command.compare("CMD_SET_COMMAND_RAW")){
            CReportManager::getInstance().cmd_response(0ll, cmd_id, command, -1, "暂不支持原始报文指令");
        } else if(0 == command.compare("CMD_GET_COMMAND_RULE")){
            run_cmd(cm, tm, mm, TASK_TYPE_GET_CMD_RULE, cmd_id, data);
        } else if(0 == command.compare("CMD_SET_SCENE")){
            //设置场景
            cm->c_scene_id = scene_apply(data);
            tm->run_scene(cm, mm);
            CReportManager::getInstance().cmd_response(0ll, cmd_id, command, 0, "设置场景成功");

        } else if(0 == command.compare("CMD_GET_LOG")){
            //
        } else if(0 == command.compare("CMD_REPORT_LOG")){
            //
        } else if((0 == command.compare("CMD_UPGRADE_STATE_REPORT")) || 
                    (0 == command.compare("CMD_UPGRADE")) || 
                    (0 == command.compare("CMD_EXECUTE_COMMAND"))) {
        } else {
            CReportManager::getInstance().cmd_response(0ll, cmd_id, command, -1, "接收到下发消息，无相应命令");
        }
    } else if(j.contains("command") && j.contains("commandType") && (0 == j["commandType"].get<std::string>().compare("REP"))){
    } else {
    	CReportManager::getInstance().cmd_response(0ll, j["commandId"].get<int64_t>(), "UNKNOWN", -1, "命令执行失败");
    }
    return 0;
}
int64_t JsonManager::scene_apply(std::string data){
    json j = json::parse(data);
    if(j.contains("params") && j["params"].contains("sceneId")){
        return j["params"]["sceneId"].get<int64_t>();
    } else {
        return 0;
    }
}
//
int JsonManager::parse_config(std::shared_ptr<CConfigManager> cm, std::shared_ptr<TaskManager> tm, std::shared_ptr<CMosquittoManager> mm, std::shared_ptr<DataCenterManager> dcm, std::string data){
    json j = json::parse(data);
    CONFIG_ALL configs = j;
    auto edge_dev = configs.edge_devices.begin();
    auto old_edge_dev = cm->get_edge_devices()->begin();
    if(edge_dev != configs.edge_devices.end()){
        for(auto terminal_dev = configs.terminal_devices.begin(); terminal_dev != configs.terminal_devices.end(); terminal_dev++){
            for(auto serial = edge_dev->serials.begin(); serial != edge_dev->serials.end(); serial++){
                if(serial->id == terminal_dev->com_index){
                    terminal_dev->channel = serial->addr;
                }
            }
        }
    } else {
        if(old_edge_dev != cm->get_edge_devices()->end()){
            for(auto terminal_dev = configs.terminal_devices.begin(); terminal_dev != configs.terminal_devices.end(); terminal_dev++){
	            for(auto serial = old_edge_dev->second.serials.begin(); serial != old_edge_dev->second.serials.end(); serial++){
	                if(serial->id == terminal_dev->com_index){
	                    terminal_dev->channel = serial->addr;
	                }
	            }
        	}
    	}
	}
    //在此处保存数据
    CDBManager::getInstance()->insert_config_all(configs);
    std::shared_ptr<CONFIG_ALL>  config = std::make_shared<CONFIG_ALL>(configs);
    cm->parse(config);

    //向数据中心注册模型和设备
    dcm->devregister_modelset_todc();

    //向104模块发送信号，退出104通信
    if (g_104north_enable){
        raise(SIGUSR1);
    }
    
    //延迟1s重启，避免应答无法正常发出。
    std::thread t1(exec_self, g_argv);
    t1.detach();

    return 0;
}
/**
 * @brief 可通过在上报时判断该点是不是命令执行的采集数据决定是否立即上报。
 * 
 * @param cm 
 * @param tm 
 * @param mm 
 * @param type 
 * @param req_id 
 * @param data 
 * @return int 
 */
int JsonManager::run_cmd(std::shared_ptr<CConfigManager> cm, std::shared_ptr<TaskManager> tm, std::shared_ptr<CMosquittoManager> mm, TASK_TYPE type, int64_t req_id, std::string data){
    //在此处保存数据
    json j = json::parse(data);

    TASK_PARAMS param;
    param.dev_id    = -1;
    // param.point_id  = -1;
    param.dev = "";
    param.req_id    = req_id;
    param.type      = type;
    param.priority  = 1;
    param.topic     = "";
    param.cmd_source= CMD_FROM_CLOUD;

    if(j.contains("devId")){
        json_to_obj<int64_t>(j, "devId", param.dev_id);
    }
    
    if(j.contains("params")){
        //读取指令
        if(TASK_TYPE_GET_CMD_RULE == type){
            if(j["params"].contains("pointId")){
                int point_id = -1;
                ITEM_PARAMS item;
                json_to_obj<int64_t>(j["params"], "pointId", item.item_id);
                param.items.push_back(item);
                if(0 > item.item_id){
                    return -1;
                }
            }
        } else if(TASK_TYPE_SET_CMD_RULE == type){ 
            //控制指令
            ITEM_PARAMS item;
            if(j["params"].contains("cmdId")){
                json_to_obj<int64_t>(j["params"], "cmdId", item.item_id);
                if(0 > item.item_id){
                    return -1;
                }
            }
            //此处写值
            if(j["params"].contains("value")){
                json_to_obj<std::string>(j["params"], "value", item.value);
            }
            param.items.push_back(item);
        } else {
            CLogger::getInstance()->log_w("暂不支持的指令形式");
            return -1;
        }
    } else {
        CLogger::getInstance()->log_w("指令参数异常");
    }
    if(0 > param.dev_id){
        return -1;
    }
    tm->run_cmd(cm, mm, param);
    return 0;
}
/**
 *  @brief 
 *  @param serial 
 *  @return 
 */
std::string JsonManager::get_serial_info_json_str(std::shared_ptr<SERIAL_INFO> serial){
    static int num = 0;
    num++;
    std::string timestamp = "";
    get_uart_timestamp(timestamp);
    json j = {
        {"appName", "pemd"},
        {"mode", "master"},
        {"timestamp", timestamp},
        {"token", num},
        {"param", {
            {"baudRate", serial->baud_rate},
            {"byteSize", serial->data_size},
            {"parity",   serial->parity},
            {"stopBits", serial->stop_bit}
         }
        }
    }; 
    return j.dump();
}
/**
 *  @brief 
 *  @param serial 
 *  @return 
 */
CMD_REQUEST JsonManager::get_cmd_info(std::string cmd_str){
    return json::parse(cmd_str);
}

std::string JsonManager::get_set_const_value_msg(CMD_SET_CONST_VALUE data){
    json j = data;
    return j.dump();
}

std::string JsonManager::get_command_name(std::string& data){
    json j = json::parse(data);
    if(j.contains("command")){
        return j["command"].get<std::string>();
    } else {
        return "CMD_UNKNOWN";
    }
}